<style>

</style>
<template>
  <div>
    <el-dialog
        title="策略配置"
        :visible.sync="dialogVisible"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
        width="80%"
        :before-close="clearForm">

      <el-form
          :label-position="labelPosition"
          label-width="80px"
          :model="saveData"
          :rules="rules"
          ref="ruleForm"
      >
        <el-form-item label="选择域" prop="domainCode">
          <el-select
              :disabled="saveData.id && saveData.id !==''"
              filterable
              @change="domainChange"
              v-model="saveData.domainCode"
              placeholder="请选择域">
            <el-option
                v-for="item in domainOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="场景" prop="sceneCode">
          <el-select
              filterable
              @change="sceneChange"
              :disabled="saveData.domainCode === ''"
              v-model="saveData.sceneCode"
              placeholder="请选择场景">
            <el-option
                v-for="item in sceneOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="策略名称" prop="strategyName">
          <el-input v-model="saveData.strategyName"></el-input>
        </el-form-item>
        <el-form-item label="策略描述">
          <el-input :disabled="saveData.domainCode === ''" v-model="saveData.desc"></el-input>
        </el-form-item>
        <el-form-item label="数据源">
          <el-select
              filterable
              :disabled="saveData.domainCode === ''"
              v-model="saveData.dataSourceUuid"
              placeholder="请选择数据源">
            <el-option
                v-for="item in dataSourceOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
            </el-option>
          </el-select>
          <el-button v-if="saveData.dataSourceUuid!==''" type="warning" @click="dataSourceDebug">执行</el-button>
        </el-form-item>
        <el-form-item v-if="dataSourceDebugResult" label="执行结果">
          <div style="background-color: black;color:#FFD700;line-height: 20px!important;">
            <span>是否执行成功：{{ dataSourceDebugResult.success }}</span><br>
            <span v-if="dataSourceDebugResult.success"><span>实际执行结果：{{ dataSourceDebugResult.realResult }}</span><br></span>
            <span v-if="!dataSourceDebugResult.success">执行异常：{{ dataSourceDebugResult.exceptionMessage }}</span>
          </div>
        </el-form-item>
        <el-form-item label="配置类型" prop="ruleType">
          <el-select
              filterable
              :disabled="saveData.domainCode === ''"
              v-model="saveData.ruleType"
              placeholder="请选择配置类型">
            <el-option
                v-for="item in ruleTypeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="规则模式" prop="ruleMode">
          <el-select
              :disabled="saveData.domainCode === ''"
              @change="ruleModeChange"
              filterable
              v-model="saveData.ruleMode"
              placeholder="请选择规则模式">
            <el-option
                v-for="item in ruleModeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="字段清除" prop="ruleMode">
          <el-checkbox :disabled="saveData.domainCode === '' || saveData.sceneCode === ''" v-model="autoClear">规则模式切换自动清除中断相关配置数据 (如果此项禁用则需要选择场景)</el-checkbox>
        </el-form-item>
        <el-form-item label="规则簇(*)">
          <rule-tree-list ref="ruleTreeList"></rule-tree-list>
        </el-form-item>
        <el-form-item label="规则测试">
          <el-input :rows="10" type="textarea" placeholder="请输入脚本测试参数(JSON格式)" v-model="ruleDebugParam"></el-input>
        </el-form-item>
        <el-form-item v-if="ruleDebugResult" label="执行结果">
          <div style="background-color: black;color:#FFD700;line-height: 20px!important;">
            <span>请求参数：{{ ruleDebugResult.executorParam }}</span><br>
            <span>是否执行成功：{{ ruleDebugResult.success }}</span><br>
            <span>返回值是否是布尔类型：{{ ruleDebugResult.retBoolean }}</span><br>
            <span v-if="ruleDebugResult.success"><span>实际执行结果：{{ ruleDebugResult.retValue }}</span><br></span>
            <span v-if="!ruleDebugResult.success">执行异常：{{ ruleDebugResult.exceptionMessage }}</span>
          </div>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="clearForm">取 消</el-button>
        <el-button type="warning" @click="debug">测 试</el-button>
        <el-button :disabled="!testPass" type="primary" @click="save">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>

import {
  loadBaseDataSelector,
  loadDataSourceSelector,
  loadDomainMetadataSelector,
  loadDomainSceneSelector,
  loadDomainSelector,
  loadInterruptSelector,
  loadResultTypeSelector,
  loadRuleModeSelector,
  loadRuleTypeSelector
} from "../../../api/loadSelectorApi";
import {remoteValidateSceneCode, remoteValidateStrategyName, saveStrategy, strategyDebug} from "../../../api/strategyApi";
import ruleTreeList from "../components/ruleTreeList";
import {dataSourceDebugForUuid} from "../../../api/dataSourceApi";
import {joiner} from "../../../api/common";

export default {
  name: "strategyForm",
  filters: {},
  components: {
    ruleTreeList
  },
  data() {
    const validateStrategyName = async (rule, value, callback) => {
      if (this.saveData.id) {
        callback()
      }
      if (this.saveData.domainCode === '') {
        callback(new Error("请先选择域"))
      }
      let ret = await remoteValidateStrategyName(this.saveData.domainCode, value);
      if (ret.data.result) {
        callback()
      } else {
        callback(new Error("策略名字不能重复"))
      }
    };
    const validateSceneCode = async (rule, value, callback) => {
      if (this.saveData.id) {
        callback()
      }
      if (this.saveData.domainCode === '') {
        callback(new Error("请先选择域"))
      }
      if (this.saveData.sceneCode === '') {
        callback(new Error("请选择域Code"))
        return;
      }
      let ret = await remoteValidateSceneCode(this.saveData.domainCode, value);
      if (ret.data.result) {
        callback()
      } else {
        callback(new Error("此场景已经被占用"))
      }
    };
    return {
      labelPosition: 'right',
      dialogVisible: false,
      autoClear: true,
      saveData: {
        domainCode: '',
        strategyName: '',
        sceneCode: '',
        dataSourceUuid: '',
        ruleType: 'LIST',
        ruleMode: 'SIMPLE',
        desc: '',
        ruleListInfo: {
          conditions: [
            {
              group: [
                {
                  name: '',
                  leftValue: '',
                  operator: '',
                  rightValue: '',
                  interrupt: '',
                  resultType: '',
                  returnVal: '',
                  children: []
                }
              ]
            }
          ]
        },
        ruleTreeInfo: {
          conditions: [
            {
              group: [
                {
                  name: '',
                  leftValue: '',
                  operator: '',
                  rightValue: '',
                  interrupt: '',
                  resultType: '',
                  returnVal: '',
                  children: []
                }
              ]
            }
          ]
        }
      },
      rules: {
        domainCode: [
          {required: true, message: '此项必填', trigger: 'change'},
        ],
        strategyName: [
          {required: true, message: '此项必填', trigger: 'blur'},
          {validator: validateStrategyName, trigger: 'blur'}
        ],
        sceneCode: [
          {required: true, message: '此项必填', trigger: 'change'},
          {validator: validateSceneCode, trigger: 'change'}
        ],
        ruleType: [
          {required: true, message: '此项必填', trigger: 'change'},
        ],
        ruleMode: [
          {required: true, message: '此项必填', trigger: 'change'},
        ],
      },
      domainOptions: [],
      dataSourceOptions: [],
      sceneOptions: [],
      ruleTypeOptions: [],
      ruleModeOptions: [],
      // selector
      selectors: {
        leftOptions: [],
        interruptOptions: [],
        resultTypeOptions: [],
        metadataOptions: [],
      },
      // debug
      dataSourceDebugResult: undefined,
      ruleDebugParam: '',
      ruleDebugResult: undefined,
      testPass: false
    }
  },
  created() {
  },
  mounted() {
  },
  methods: {
    async load(data) {
      let vm = this
      vm.domainOptions = await loadDomainSelector();
      vm.ruleTypeOptions = await loadRuleTypeSelector();
      vm.ruleModeOptions = await loadRuleModeSelector();
      if (data) {
        let saveData = vm.$cloneObj(data);
        vm.preReload(saveData);
        vm.saveData = saveData
        if (data.domainCode) {
          vm.dataSourceOptions = await loadDataSourceSelector(data.domainCode);
          vm.sceneOptions = await loadDomainSceneSelector(data.domainCode);
          await vm.loadSelectors(data.domainCode);
        }
      }
      vm.dialogVisible = true

      vm.$nextTick(async () => {
        // 组件
        vm.$refs.ruleTreeList.load({data: vm.saveData, selectors: vm.selectors});
      })
    },
    preReload(saveData) {
      let conditions = saveData.ruleListInfo.conditions;
      for (let i = 0; i < conditions.length; i++) {
        let group = conditions[i].group;
        for (let j = 0; j < group.length; j++) {
          if (group[j].operator === 'INCLUDED') {
            group[j].rightValue = group[j].rightValue.split("::")
          }
        }
      }
    },
    async domainChange(domain) {
      let vm = this

      vm.$nextTick(() => {
        if (vm.saveData.sceneCode !== '') {
          vm.$refs.ruleTreeList.toDisabled = false
        }
      })

      vm.dataSourceOptions = await loadDataSourceSelector(domain);
      vm.sceneOptions = await loadDomainSceneSelector(domain);

      vm.saveData.sceneCode = ''
      vm.saveData.dataSourceUuid = ''

      let conditions = vm.saveData.ruleListInfo.conditions;
      let deleteConditionLength = conditions.length - 1;
      for (let i = 0; i < deleteConditionLength; i++) {
        conditions.splice(0, 1)
      }
      // 此时只会剩下一组
      let group = conditions[0].group;
      let deleteGroupLength = group.length - 1;
      for (let i = 0; i < deleteGroupLength; i++) {
        group.splice(0, 1)
      }
      // 值复原
      group[0].name = ''
      group[0].leftValue = ''
      group[0].operator = ''
      group[0].rightValue = ''
      group[0].interrupt = ''
      group[0].resultType = ''
      group[0].returnVal = ''
      group[0].children = []

      await vm.loadSelectors(domain);
    },
    async loadSelectors(domain) {
      let vm = this
      // selectors
      vm.selectors.leftOptions = await loadBaseDataSelector(domain)
      vm.selectors.interruptOptions = await loadInterruptSelector()
      vm.selectors.resultTypeOptions = await loadResultTypeSelector()
      vm.selectors.metadataOptions = await loadDomainMetadataSelector(domain)
    },
    sceneChange(value) {
      this.$refs.ruleTreeList.toDisabled = false
    },
    save() {
      let vm = this
      this.$refs['ruleForm'].validate(async (valid) => {
        if (valid) {
          if (!vm.ruleValidator()) {
            return;
          }
          await vm.doSave(vm.preSave())
        }
      })
    },
    preSave() {
      let saveData = this.$cloneObj(this.saveData);
      let conditions = saveData.ruleListInfo.conditions;
      for (let i = 0; i < conditions.length; i++) {
        let group = conditions[i].group;
        for (let j = 0; j < group.length; j++) {
          if (group[j].rightValue instanceof Array) {
            group[j].rightValue = joiner(group[j].rightValue, "::")
          }
        }
      }
      return saveData;
    },
    async doSave(saveData) {
      let vm = this
      let ret = await saveStrategy(saveData);
      if (ret.ok) {
        vm.$message({type: 'success', message: '保存成功!'});
      } else {
        vm.$message({type: 'error', message: '保存失败：' + ret.message});
      }
      vm.clearForm()
      vm.$parent.query()
    },
    clearForm() {
      let vm = this
      try {
        vm.saveData = {
          domainCode: '',
          strategyName: '',
          sceneCode: '',
          dataSourceUuid: '',
          ruleType: 'LIST',
          ruleMode: 'SIMPLE',
          desc: '',
          ruleListInfo: {
            conditions: [
              {
                group: [
                  {
                    name: '',
                    leftValue: '',
                    operator: '',
                    rightValue: '',
                    interrupt: '',
                    resultType: '',
                    returnVal: '',
                    children: []
                  }
                ]
              }
            ]
          },
          ruleTreeInfo: {
            conditions: [
              {
                group: [
                  {
                    name: '',
                    leftValue: '',
                    operator: '',
                    rightValue: '',
                    interrupt: '',
                    resultType: '',
                    returnVal: '',
                    children: []
                  }
                ]
              }
            ]
          }
        }
        vm.dataSourceOptions = []
        vm.sceneOptions = []
        vm.dataSourceDebugResult = undefined
        vm.ruleDebugResult = undefined
        vm.ruleDebugParam = ''
        vm.testPass = false
        vm.$refs['ruleForm'].resetFields()
      } catch (e) {
        console.log(e)
      }
      vm.dialogVisible = false
    },
    ruleModeChange(value) {
      let vm = this
      vm.$refs.ruleTreeList.ruleMode = value
      // 如果切换为简单模式，则清除数据
      if (value === 'SIMPLE' && vm.autoClear) {
        let conditions = vm.saveData.ruleListInfo.conditions;
        for (let i = 0; i < conditions.length; i++) {
          let group = conditions[i].group;
          for (let j = 0; j < group.length; j++) {
            group[i].interrupt = ''
            group[i].resultType = ''
            group[i].returnVal = ''
          }
        }
      }
    },
    async dataSourceDebug() {
      let ret = await dataSourceDebugForUuid(this.saveData.dataSourceUuid);
      if (ret.ok) {
        this.dataSourceDebugResult = ret.data.result
      } else {
        this.$message({type: 'error', message: '测试失败：' + ret.message});
      }
    },
    async debug() {
      // 数据验证
      let vm = this
      if (!vm.ruleValidator()) {
        return;
      }
      let ret = await strategyDebug(vm.preSave(), vm.ruleDebugParam);
      if (ret.ok) {
        vm.ruleDebugResult = ret.data.result
        vm.testPass = vm.ruleDebugResult.success
      } else {
        vm.$message({type: 'error', message: '测试失败：' + ret.message});
      }
    },
    ruleValidator() {
      let vm = this
      let format = '规则簇第{0}组，第{1}条规则的[{2}]不能为空'
      let ruleListInfo = vm.saveData.ruleListInfo;
      let conditions = ruleListInfo.conditions;
      for (let i = 0; i < conditions.length; i++) {
        let group = conditions[i].group;
        for (let j = 0; j < group.length; j++) {
          if (group[j].name.trim() === '') {
            vm.$message({type: 'error', message: format.format(i + 1, j + 1, "名字")});
            return false;
          }
          if (group[j].leftValue.trim() === '') {
            vm.$message({type: 'error', message: format.format(i + 1, j + 1, "左值")});
            return false;
          }
          if (group[j].operator.trim() === '') {
            vm.$message({type: 'error', message: format.format(i + 1, j + 1, "操作符")});
            return false;
          }
          if (group[j].rightValue instanceof String && group[j].rightValue.trim() === '') {
            vm.$message({type: 'error', message: format.format(i + 1, j + 1, "右值")});
            return false;
          }
          if (group[j].rightValue instanceof Array && group[j].rightValue.length === 0) {
            vm.$message({type: 'error', message: format.format(i + 1, j + 1, "右值")});
            return false;
          }
          if (group[j].rightValue === '') {
            vm.$message({type: 'error', message: format.format(i + 1, j + 1, "右值")});
            return false;
          }
          if (vm.saveData.ruleMode === 'COMPLEX') {
            if (group[j].interrupt.trim() === '') {
              vm.$message({type: 'error', message: format.format(i + 1, j + 1, "是否中断")});
              return false;
            }
            if (group[j].resultType.trim() === '') {
              vm.$message({type: 'error', message: format.format(i + 1, j + 1, "中断返回类型")});
              return false;
            }
            if (group[j].returnVal.trim() === '') {
              vm.$message({type: 'error', message: format.format(i + 1, j + 1, "中断返回值")});
              return false;
            }
          }
        }
      }
      return true;
    }
  },
  watch: {}
}
</script>
